#ifndef BEHAVIOR_TREE_POLICY_H
#define BEHAVIOR_TREE_POLICY_H

#include "policy/abstract_policy.h"
#include "behaviortree_cpp_v3/action_node.h"
#include <behaviortree_cpp_v3/decorator_node.h>
#include <behaviortree_cpp_v3/control_node.h>
#include <atomic>

namespace policy
{
class BehaviorTreePolicy: public AbstractPolicy
{
public:
    explicit BehaviorTreePolicy(const std::string &name);
    ~BehaviorTreePolicy() override;

    bool addTask(const task::AbstractTaskConstPtr &task) override;

    bool insertTask(int index, const task::AbstractTaskConstPtr &task) override;

    bool addPolicy(const AbstractPolicyConstPtr &policy) override;

    bool insertPolicy(int index, const AbstractPolicyConstPtr &policy) override;

    bool setTask(const task::AbstractTaskConstPtr &task) override;

    bool setPolicy(const AbstractPolicyConstPtr &policy) override;

    std::any getPolicyData() override;

    void run() final;

    void pause() final;

    void resume() final;

    void cancel() final;

    void setContext(task::Context *context) override;

    std::string toString() const override;

    BT::Optional<BT::NodeStatus> preTick(BT::TreeNode &tree_node, BT::NodeStatus node_status);

    BT::Optional<BT::NodeStatus> postTick(BT::TreeNode &tree_node, BT::NodeStatus node_status, BT::NodeStatus new_status);

private:
    BT::ActionNodeBase *createActionNode(const std::string &name, const BT::NodeConfiguration &config,
                                         const std::shared_ptr<task::AbstractTask> &task);

protected:
    std::unique_ptr<BT::TreeNode> policy_tree_node_;
    std::vector<std::shared_ptr<BT::TreeNode> > node_vector_;
    std::vector<AbstractPolicy *> policy_vector_;

    class ControlProxy;
    std::unique_ptr<ControlProxy> ctrl_proxy_;
};

}


#endif //BEHAVIOR_TREE_POLICY_H
